package web.service.impl;


import io.jsonwebtoken.Claims;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Component;
import web.bo.WebsiteEntityBo;
import web.common.CutPageBean;
import web.entity.WebsiteEntity;
import web.mapper.WebsiteMapper;
import web.utils.IPutil;
import web.utils.JwtUtil;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Description:流量统计实现类
 *
 * @author BaiGe
 * @date: 2022/8/8 16:33
 * @Version 1.0
 */
@Component
public class WebsiteService {
    public static final String VISIT_COOKIE_NAME = "mydxWebSite"; // cookie名
    public static final String PV_TYPE = "pv"; // pv
    public static final String UV_TYPE = "uv"; // uv
    public static final String IP_TYPE = "ip"; // ip
    @Resource
    private WebsiteMapper websiteMapper;

    public Map webSiteLog(HttpServletRequest request, WebsiteEntity websiteEntity) {
        String nowTime = this.getCurrentTime("yyyy-MM-dd HH:mm:ss");
//        String nowTime = this.getCurrentTime("yyyy-MM-dd");
        websiteEntity.setRecordTime(nowTime);
        /*****************IP********************/
        this.handleIp(request, websiteEntity);
        /******************UV**************************/
        Map map = this.handleUV(request, websiteEntity);
        /*******************PV*******************/
        this.handlePV(request, websiteEntity);
        return map;
    }

    /**
     * 处理pv记录
     *
     * @param websiteEntity
     */
    public void handlePV(HttpServletRequest request, WebsiteEntity websiteEntity) {
        //设置类型
        websiteEntity.setType(PV_TYPE);

        websiteEntity = updateWebsiteEntity(websiteEntity,request);

        websiteMapper.insertPv(websiteEntity);
    }

    /**
     * 插入UV记录
     *
     * @param websiteEntity
     * @param request
     * @param
     */
    public Map handleUV(HttpServletRequest request, WebsiteEntity websiteEntity) {
        Map<String, String> map = new HashMap<>();
        String cookie = request.getHeader(VISIT_COOKIE_NAME);
        if (!StringUtils.isNotBlank(cookie)) { //header中的cookie为空
            String cookieValue = UUID.randomUUID().toString();
            long time = System.currentTimeMillis() + this.getCookieDeath();
            String expiresTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(time);
            map.put("judge", "handle");
            map.put("expires", expiresTime);
            map.put("mydxWebSite", cookieValue);
            //设置类型
            websiteEntity.setType(UV_TYPE);
            //插入UV
            websiteEntity = updateWebsiteEntity(websiteEntity,request);
            websiteMapper.insertUv(websiteEntity);
        } else {
            map.put("judge", "notHandle");
            map.put("expires", "");
            map.put("mydxWebSite", "");
        }
        return map;
    }


    public void handleIp(HttpServletRequest request, WebsiteEntity websiteEntity) {
        // 获取请求的 IP
        String remoteAddr = IPutil.getIpAddr(request);
        if (StringUtils.isNotBlank(remoteAddr)) {
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
            long millis = System.currentTimeMillis();
            String preDate = dateFormat.format(millis - 86400000l) + " 23:59:59";
            String nextDate = dateFormat.format(millis + 86400000l) + " 01:00:00";
            // 如果今天之类,db中已经保存了该 ip，那么就不记录
            List<WebsiteEntity> list = websiteMapper.queryHasRecord(remoteAddr, preDate, nextDate);
            if (list == null || list.isEmpty()) {//如果没有ip记录
                //设置类型
                websiteEntity.setType(IP_TYPE);
                websiteEntity.setRemoteAddr(remoteAddr);
                //插入Ip记录
                websiteEntity = updateWebsiteEntity(websiteEntity,request);
                websiteMapper.insertIp(websiteEntity);
            }
        }
    }

    public List<Map> numStatistics() {
        List<Map> maps = websiteMapper.getNumGroupByType();
        return maps;
    }

    public List<Map> getWebSiteNumByDateAndType(String date) {
        List<Map> maps = websiteMapper.getWebSiteNumByDateAndType(date);
        return maps;
    }

    public Map reportForm(String fromDate, String toDate) {
        List<Map> maps = websiteMapper.reportForm(fromDate, toDate);

        List<Map> pvMaps = maps.stream().filter(map -> map.get("type") != null && map.get("type").equals("pv")).collect(Collectors.toList());
        List<Map> uvMaps = maps.stream().filter(map -> map.get("type") != null && map.get("type").equals("uv")).collect(Collectors.toList());
        List<Map> ipMaps = maps.stream().filter(map -> map.get("type") != null && map.get("type").equals("ip")).collect(Collectors.toList());

        Map<String,List<Map>> resultMap=new HashMap<>();
        resultMap.put("pv",pvMaps);
        resultMap.put("uv",uvMaps);
        resultMap.put("ip",ipMaps);

        return resultMap;
    }

    public Map  getReportFormByDate(String date){
        List<Map> maps = websiteMapper.getReportFormByDate(date);
        List<Map> pvMaps = maps.stream().filter(map -> map.get("type") != null && map.get("type").equals("pv")).collect(Collectors.toList());
        List<Map> uvMaps = maps.stream().filter(map -> map.get("type") != null && map.get("type").equals("uv")).collect(Collectors.toList());
        List<Map> ipMaps = maps.stream().filter(map -> map.get("type") != null && map.get("type").equals("ip")).collect(Collectors.toList());

        Map<String,Object> resultMap=new HashMap<>();
        resultMap.put("pv",pvMaps);
        resultMap.put("uv",uvMaps);
        resultMap.put("ip",ipMaps);

        return resultMap;
    }

    public  List<Map> top10SearchWord(){
     return    websiteMapper.top10SearchWord();
    }


    public String getCurrentTime(String format) {
        SimpleDateFormat dateFormat = new SimpleDateFormat(format);
        String nowDate = dateFormat.format(new Date());
        return nowDate;
    }

    /**
     * 获取当天23:59:59的时间
     *
     * @return
     */
    public static int getCookieDeath() {
        // 获取当前时间戳
        long now = Calendar.getInstance().getTimeInMillis();

        // 通过 Calendar 手动设置时间
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);

        // 获取当日 23:59:59 的时间戳
        long death = calendar.getTimeInMillis();

        // 计算过期时间
        // 注意：cookie 过期时间的单位为秒
        int cookieMaxAge = (int) ((death - now));

        return cookieMaxAge;
    }

    /**
     * 后续需求：额外记录 ①用户名称 ②用户账号
     * 用户名称来自前端参数
     * 用户账号来自请求头 Mydx_token
     * @param entity 前端入参
     * @param request HttpServletRequest
     * @return entity
     */
    WebsiteEntity updateWebsiteEntity(WebsiteEntity entity,HttpServletRequest request){
        // 获取请求的 IP
        String remoteAddr = IPutil.getIpAddr(request);
        entity.setRemoteAddr(remoteAddr);
        //账号
        String account = "";
        try {
            Claims claims = JwtUtil.parseJWT(request.getHeader("Mydx_token"));
            account = claims.getSubject();
        } catch (Exception e) {
            e.printStackTrace();
        }
        entity.setAccount(account);
        return entity;
    }


    public CutPageBean<WebsiteEntity> urlAccessLogList_notChoice(WebsiteEntityBo websiteEntityBo) {
        List<WebsiteEntity> res= websiteMapper.urlAccessLogList_notChoice(websiteEntityBo);
        Integer count = websiteMapper.urlAccessLogList_notChoiceCounter(websiteEntityBo);
        CutPageBean<WebsiteEntity> cutPage = new CutPageBean<>();
        cutPage.initCutPage(count, websiteEntityBo.getPageSize(), res);
        return cutPage;
    }

    public CutPageBean<Map> urlAccessLogList_choiceUsername(WebsiteEntityBo websiteEntityBo) {
        List<Map> res= websiteMapper.urlAccessLogList_choiceUsername(websiteEntityBo);
        Integer count = websiteMapper.urlAccessLogList_choiceUsernameCounter(websiteEntityBo);
        CutPageBean<Map> cutPage = new CutPageBean<>();
        cutPage.initCutPage(count, websiteEntityBo.getPageSize(), res);
        return cutPage;
    }
}

